#pragma once
#include<iostream>
#include<string>
#include<fstream>
#include<cstdio>
#include<ctime>
#include<cstdarg>
#include<sys/types.h>
#include<unistd.h>
#include<pthread.h>
#include"LockGuard.hpp"

bool gIsSave = false;
const std::string logname = "log.txt";

enum level
{
    DEBUG = 0,
    INFO,
    WARNING,
    ERROR,
    FATAL

};

void SaveFile(const std::string &filename, const std::string &message) // 文件名，消息
{
    std::ofstream out(filename, std::ios::app);
    if (!out.is_open())
    {
        return;
    }
    out << message;
    out.close(); //
}

// 日志信号

std::string LevelToString(int level)
{
    switch (level)
    {
    case DEBUG:
        return "debug";
    case INFO:
        return "info";
    case WARNING:
        return "warning";
    case ERROR:
        return "error";
    case FATAL:
        return "fatal";
    default:
        return "Unknown";
    }
}

// 文件时间
std::string GetTimeString()
{
    time_t curr_time = time(nullptr);
    struct tm *format_time = localtime(&curr_time);
    if (format_time == nullptr)
    {
        return"None";
    }
    char time_burrer[1024];
    snprintf(time_burrer, sizeof(time_burrer), "%d-%d-%d %d:%d:%d", 
                                    format_time->tm_year + 1900, 
                                    format_time->tm_mon + 1,
                                    format_time->tm_mday,
                                     format_time->tm_hour,
                                      format_time->tm_min, 
                                         format_time->tm_sec);
    return time_burrer;
}

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

// 输出日志内容时间行数
void LogMessage(std::string filename, int line, bool issave, int level, const char *format, ...)
{
    std::string levelstr = LevelToString(level);
    std::string timestr = GetTimeString();
    pid_t selfid = getpid();

    char buffer[1024];
    va_list arg;
    va_start(arg, format);
    vsnprintf(buffer, sizeof(buffer), format, arg);
    va_end(arg);

    std::string message = "[" + timestr + "]" + "[" + levelstr + "]" + "[" + std::to_string(selfid) + "]" + "[" + filename + "]" + "[" + std::to_string(line) + "]" + buffer;
    LockGuard lockguard(&lock);

    if (!issave)
    {
        std::cout << message;
    }
    else
    {
        SaveFile(logname, message); // 消息打印到log.txt中
    }
}

#define LOG(level, format, ...)                                                \
    do                                                                         \
    {                                                                          \
        LogMessage(__FILE__, __LINE__, gIsSave, level, format, ##__VA_ARGS__); \
    } while(0)
#define EnableFile()    \
    do                  \
    {                   \
        gIsSave = true; \
    } while(0)
#define EnableScreen()   \
    do                   \
    {                    \
        gIsSave = false; \
    } while(0)